#include <array>
#include <bitset>
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <cstdint>
#include <random>

using Byte16 = std::array<uint8_t,16>;

// 通用哈希 + 掩码 PRF，输入 128→输出 128，安全参数 ≥32
class UniversalHashMask128 {
private:
    // 编译期固定的“随机”常量（4 组 a_i、b_i，以及 16 字节 mask）
    // static constexpr 隐式 inline（C++17起），可直接在类内初始化【:contentReference[oaicite:0]{index=0}】【】
    inline static constexpr uint64_t a[4] = {
        0x21A1CE4D3F4895EFULL,
        0xD36163902D91908DULL,
        0xC43EAAF690B4E1E7ULL,
        0xC8D60DE5F82A1C29ULL
    };
    inline static constexpr uint64_t b[4] = {
        0x7C20BA20EF2F9895ULL,
        0x7DDE6BE1A1B6B5D6ULL,
        0x679BCAFB330C9BEFULL,
        0xD6030BB550350A0EULL
    };
    inline static constexpr uint8_t mask[16] = {
        0x5E, 0xAC, 0x33, 0x0A, 0xE9, 0x97, 0xFE, 0x33,
        0x13, 0x46, 0x87, 0x74, 0x4C, 0x1B, 0x8E, 0x22
    };

public:
    Byte16 operator()(const Byte16 &in) const {
        // 拆 128 位为 4×32 位小端整数
        uint32_t x[4];
        for(int i=0;i<4;i++){
            x[i] = uint32_t(in[4*i])
                 | uint32_t(in[4*i+1])<<8
                 | uint32_t(in[4*i+2])<<16
                 | uint32_t(in[4*i+3])<<24;
        }
        // 计算哈希并 XOR 掩码
        Byte16 out;
        for(int i=0;i<4;i++){
            uint64_t t = a[i] * uint64_t(x[i]) + b[i];  // 模 2^64 运算【:contentReference[oaicite:2]{index=2}】
            uint32_t hi = uint32_t(t >> 32);            // 取高 32 位
            for(int j=0;j<4;j++){
                out[4*i + j] = uint8_t((hi >> (8*j)) & 0xFF) ^ mask[4*i + j];
            }
        }
        return out;
    }
};

void xor_arrays(std::array<uint8_t, 16>& a, std::array<uint8_t, 16>& b){
    std::array<uint8_t, 16> result;
    for (size_t i = 0; i < 16; ++i) {
        b[i]^= a[i];
    }
    return;
}
// 布谷鸟hash->128
void simple_hash20(const std::array<uint8_t, 20>& input_block,  std::array<uint8_t, 16>& hash_value) {
    hash_value.fill(0);//初始化为0
    // 迭代处理每个字节
    for (size_t i = 0; i < 20; ++i) {
        // 将输入字节与当前哈希值进行异或、移位、加法等操作
        for (size_t j = 0; j < 16; ++j) {
            hash_value[j] ^= input_block[i] + j;
            hash_value[j] = (hash_value[j] << 3) | (hash_value[j] >> 5);  // 循环左移3位
        }
    }
}

inline uint64_t rotl64(uint64_t x, int8_t r) {
    return (x << r) | (x >> (64 - r));
}

inline uint64_t fmix64(uint64_t k) {
    k ^= k >> 33;
    k *= 0xff51afd7ed558ccd;
    k ^= k >> 33;
    k *= 0xc4ceb9fe1a85ec53;
    k ^= k >> 33;
    return k;
}

void pack_memcpy(uint64_t h1, uint64_t h2, Byte16& out) noexcept {
    std::memcpy(out.data(),     &h1, sizeof h1);     // 拷贝 h1 的 8 字节 :contentReference[oaicite:0]{index=0}  
    std::memcpy(out.data() + 8, &h2, sizeof h2);     // 拷贝 h2 的 8 字节 :contentReference[oaicite:1]{index=1}  
    return ;
}

void MurmurHash3_x64_128(const void* key, int len, uint32_t seed, Byte16& out) {
    const uint8_t* data = static_cast<const uint8_t*>(key);
    const int nblocks = len / 16;
    uint64_t h1 = seed;
    uint64_t h2 = seed;

    const uint64_t* blocks = reinterpret_cast<const uint64_t*>(data);
    for (int i = 0; i < nblocks; ++i) {
        uint64_t k1 = blocks[i * 2];
        uint64_t k2 = blocks[i * 2 + 1];

        k1 *= 0x87c37b91114253d5;
        k1 = rotl64(k1, 31);
        k1 *= 0x4cf5ad432745937f;
        h1 ^= k1;

        h1 = rotl64(h1, 27);
        h1 += h2;
        h1 = h1 * 5 + 0x52dce729;

        k2 *= 0x4cf5ad432745937f;
        k2 = rotl64(k2, 33);
        k2 *= 0x87c37b91114253d5;
        h2 ^= k2;

        h2 = rotl64(h2, 31);
        h2 += h1;
        h2 = h2 * 5 + 0x38495ab5;
    }

    const uint8_t* tail = data + nblocks * 16;
    uint64_t k1 = 0;
    uint64_t k2 = 0;
    switch (len & 15) {
        case 15: k2 ^= uint64_t(tail[14]) << 48;
        case 14: k2 ^= uint64_t(tail[13]) << 40;
        case 13: k2 ^= uint64_t(tail[12]) << 32;
        case 12: k2 ^= uint64_t(tail[11]) << 24;
        case 11: k2 ^= uint64_t(tail[10]) << 16;
        case 10: k2 ^= uint64_t(tail[9]) << 8;
        case 9:  k2 ^= uint64_t(tail[8]);
                 k2 *= 0x4cf5ad432745937f;
                 k2 = rotl64(k2, 33);
                 k2 *= 0x87c37b91114253d5;
                 h2 ^= k2;
        case 8:  k1 ^= uint64_t(tail[7]) << 56;
        case 7:  k1 ^= uint64_t(tail[6]) << 48;
        case 6:  k1 ^= uint64_t(tail[5]) << 40;
        case 5:  k1 ^= uint64_t(tail[4]) << 32;
        case 4:  k1 ^= uint64_t(tail[3]) << 24;
        case 3:  k1 ^= uint64_t(tail[2]) << 16;
        case 2:  k1 ^= uint64_t(tail[1]) << 8;
        case 1:  k1 ^= uint64_t(tail[0]);
                 k1 *= 0x87c37b91114253d5;
                 k1 = rotl64(k1, 31);
                 k1 *= 0x4cf5ad432745937f;
                 h1 ^= k1;
    }

    h1 ^= len;
    h2 ^= len;

    h1 += h2;
    h2 += h1;
    pack_memcpy(fmix64(h1),fmix64(h2),out);
}
// 布谷鸟hash->128
void hash20(const std::array<uint8_t, 20>& input_block,  std::array<uint8_t, 16>& hash_value) {
    MurmurHash3_x64_128(input_block.data(),20,0x12345678,hash_value);
}


int main(int argc, char* argv[]) {
    if(argc != 3) {
        std::cout << "Usage: " << argv[0] << " <input_file> <output_file>\n";
        return 1;
    }
    std::ifstream input_file(argv[1],std::ios::binary);
    std::ofstream output_fileliner(argv[2],std::ios::binary);
    if(!input_file.is_open() || !output_fileliner.is_open()) {
        std::cout << "Failed to open file\n";
        return 1;
    }
    UniversalHashMask128 prf;
    const size_t BLOCK_SIZE = 160 / 8;  // 160 位 = 4+16 字节
    const size_t OUTPUT_SIZE = 128 / 8; // 128 位 = 16 字节
    // 读取输入文件
    std::array<uint8_t, BLOCK_SIZE> input_block;
    std::array<uint8_t, OUTPUT_SIZE> output_block;
    std::array<uint8_t, OUTPUT_SIZE> output_block2;
    int count = 0;
    int value = 0;


    while (input_file.read(reinterpret_cast<char*>(input_block.data()), BLOCK_SIZE)) { 
        hash20(input_block,output_block);//进行hash映射 得到和布谷鸟相关的hash值。160->128;
        output_block2=prf(output_block); 
        // 写入输出文件
        output_fileliner.write(reinterpret_cast<char*>(output_block2.data()), OUTPUT_SIZE);
        count++;
    }
    
    input_file.close();
    output_fileliner.close();
    std::cout << "Processed " << count << " blocks\n";
    return 0;

}
